﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Baby.GrowUp.Data
{
    /// <summary>
    /// 对象代理,提供为未明确类型的对象属性赋值的一系列函数
    /// </summary>
    /// <typeparam name="T">该对象所代理的对象类型</typeparam>
    internal class ObjectProxy<T> where T:class
    {

        Type _targetType = null;
        T _targetObject = null;

        //目标对象的属性列表<字段名,属性信息>
        Dictionary<string, PropertyInfo> _fields = new Dictionary<string, PropertyInfo>();

        public ObjectProxy(T tarObj) {

            if (tarObj == null) {
                throw new ArgumentNullException("tarObj");
            }

            Type type = typeof(T);
            this._targetType = type;
            this._targetObject = tarObj;
            this.InitPropertys();
        }

        public ObjectProxy()
        {
            Type type = typeof(T);


            ConstructorInfo constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public,null, new Type[0],null);

            //ConstructorInfo constructor = type.GetConstructor(new Type[0]);
            if (constructor == null)
            {
                throw new ArgumentException(string.Format("{0} 类型需要一个不带参数的默认构造函数", type.FullName));
            }

            this._targetType = type;
            this._targetObject = constructor.Invoke(null) as T;
            this.InitPropertys();
        }


        /// <summary>
        /// 获取目标对象所需要绑定的字段列表
        /// </summary>
        public string[] Fields {
            get {
                return _fields.Keys.ToArray();
            
            }
        
        }


        /// <summary>
        /// 初始化目标对象中的属性信息
        /// </summary>
        private void InitPropertys()
        {

            #region 获取目标对象的字段列表

            //目标对象的属性列表

            PropertyInfo[] props = this._targetType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
            foreach (var prop in props)
            {
                if (prop.IsDefined(typeof(DataPropertyAttribute), true) && prop.CanWrite)
                {
                    DataPropertyAttribute propAttr = prop.GetCustomAttributes(typeof(DataPropertyAttribute), true)[0] as DataPropertyAttribute;
                    this._fields.Add(propAttr.Field, prop);
                }

            }
            #endregion

        }


        /// <summary>
        /// 获取目标对象
        /// </summary>
        public T TargetObject {
            get {
                return this._targetObject;
            }
        }





        /// <summary>
        /// 设置所代理的对象中指定属性的值
        /// </summary>
        /// <param name="propName">属性名称</param>
        /// <param name="value">属性值</param>
        public void SetProperty(string propName, object value)
        {

            if (propName == null) {
                throw new ArgumentNullException("propName");
            }
            if (value == null)
            {
                return;
            }

            
            PropertyInfo prop = this._targetType.GetProperty(propName);

            if (prop == null) { return; }
            if (!prop.CanWrite) { return; }

            prop.SetValue(this._targetObject, value, null);
        }


        /// <summary>
        /// 设置所代理的对象中指定字段的值
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <param name="value">值</param>
        public void SetField(string fieldName, object value)
        {
            if (fieldName == null)
            {
                throw new ArgumentNullException("fieldName");
            }
            if (value == null) { return; }
            if (value is DBNull) { return; }

            if (!this._fields.ContainsKey(fieldName)) { return; }


            PropertyInfo prop = this._fields[fieldName];
            if (!prop.CanWrite) { return; }
            prop.SetValue(this._targetObject, value, null);

        }


      



    }
}
